package l1j.server.server.model;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.logging.Level;
import java.util.logging.Logger;

import l1j.server.L1DatabaseFactory;
import l1j.server.server.GeneralThreadPool;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.serverpackets.S_NPCTalkReturn;
import l1j.server.server.utils.SQLUtil;
import l1j.server.server.utils.TimeUtil;
import l1j.server.server.utils.collections.Lists;

public class L1Rank {
        private static L1Rank _instance = new L1Rank();

        private static Logger _log = Logger.getLogger(L1Rank.class.getName());

        private L1Rank() {
                Updater updater = new Updater();
                GeneralThreadPool.getInstance().scheduleAtFixedRate(updater, 0, 60000);
                update();
        }

        private ArrayList<LevelRank> _LevelRank_All = Lists.newArrayList();
        private ArrayList<LevelRank> _LevelRank_Crown = Lists.newArrayList();
        private ArrayList<LevelRank> _LevelRank_Knight = Lists.newArrayList();
        private ArrayList<LevelRank> _LevelRank_Wizard = Lists.newArrayList();
        private ArrayList<LevelRank> _LevelRank_Elf = Lists.newArrayList();
        private ArrayList<LevelRank> _LevelRank_DarkElf = Lists.newArrayList();
        private ArrayList<LevelRank> _LevelRank_DragonKnight = Lists.newArrayList();
        private ArrayList<LevelRank> _LevelRank_Illusionist = Lists.newArrayList();
        private ArrayList<LevelRank> _LevelRank_ExtLevel = Lists.newArrayList();
        private ArrayList<ItemRank> _ItemRank_Weapon = Lists.newArrayList();
        private ArrayList<ItemRank> _ItemRank_Armor = Lists.newArrayList();

        public static L1Rank getInstance() {
                return _instance;
        }

        private static final String url_result = "rankresult";

        public void sendData_LevelRank(L1PcInstance pc, int type) {
                ArrayList<LevelRank> list = null;
                if (type == 0) {
                        list = _LevelRank_All;
                } else if (type == 1) {
                        list = _LevelRank_Crown;
                } else if (type == 2) {
                        list = _LevelRank_Knight;
                } else if (type == 3) {
                        list = _LevelRank_Wizard;
                } else if (type == 4) {
                        list = _LevelRank_Elf;
                } else if (type == 5) {
                        list = _LevelRank_DarkElf;
                } else if (type == 6) {
                        list = _LevelRank_DragonKnight;
                } else if (type == 7) {
                        list = _LevelRank_Illusionist;
                }
                String data[] = new String[51];
                for (int i = 0; i < data.length; i++) {
                        data[i] = " ";
                }
                int i = 0;
                data[i++] = "更新時間：" + _lastUpdateTime;
                for (LevelRank rank : list) {
                        data[i++] = i + ". LV." + rank._level + "  " + rank._name;
                }
                pc.sendPackets(new S_NPCTalkReturn(0, url_result, data));
        }

        public void sendDataItemRank(L1PcInstance pc, int type) {
                ArrayList<ItemRank> list = null;
                if (type == 0) {
                        list = _ItemRank_Weapon;
                } else if (type == 1) {
                        list = _ItemRank_Armor;
                }
                String data[] = new String[51];
                for (int i = 0; i < data.length; i++) {
                        data[i] = " ";
                }
                int i = 0;
                data[i++] = "更新時間：" + _lastUpdateTime;
                for (ItemRank rank : list) {
                        data[i++] = i + ". " + rank._charName + " 的 +" + rank._enchant
                                        + " " + rank._itemName;
                }
                pc.sendPackets(new S_NPCTalkReturn(0, url_result, data));
        }

        private static String _lastUpdateTime;

        class Updater implements Runnable {
                public void run() {
                        if (TimeUtil.Minute() == 0) {// 整點
                                update();
                        }
                }
        }

        private void update() {
                Calendar c = Calendar.getInstance();
                _lastUpdateTime = TimeUtil.CalendarToString(c);
                Connection con = null;
                PreparedStatement pstm = null;
                ResultSet rs = null;
                try {
                        con = L1DatabaseFactory.getInstance().getConnection();
                        // All Level Rank
                        _LevelRank_All.clear();
                        pstm = con
                                        .prepareStatement("select level,char_name from characters where accesslevel = 0 order by exp desc limit 0,50");
                        rs = pstm.executeQuery();
                        while (rs.next()) {
                                _LevelRank_All.add(new LevelRank(rs.getInt("level"), rs
                                                .getString("char_name")));
                        }
                        Collections.sort(_LevelRank_All);

                        // Crown Level Rank
                        _LevelRank_Crown.clear();
                        pstm = con
                                        .prepareStatement("select level,char_name from characters where (class = 0 or class = 1)  and accesslevel = 0 order by exp desc limit 0,10");
                        rs = pstm.executeQuery();
                        while (rs.next()) {
                                _LevelRank_Crown.add(new LevelRank(rs.getInt("level"), rs
                                                .getString("char_name")));
                        }
                        Collections.sort(_LevelRank_Crown);

                        // Knight Level Rank
                        _LevelRank_Knight.clear();
                        pstm = con
                                        .prepareStatement("select level,char_name from characters where (class = 61 or class = 48)  and accesslevel = 0 order by exp desc limit 0,10");
                        rs = pstm.executeQuery();
                        while (rs.next()) {
                                _LevelRank_Knight.add(new LevelRank(rs.getInt("level"), rs
                                                .getString("char_name")));
                        }
                        Collections.sort(_LevelRank_Knight);

                        // Wizard Level Rank
                        _LevelRank_Wizard.clear();
                        pstm = con
                                        .prepareStatement("select level,char_name from characters where (class = 734 or class = 1186)  and accesslevel = 0 order by exp desc limit 0,10");
                        rs = pstm.executeQuery();
                        while (rs.next()) {
                                _LevelRank_Wizard.add(new LevelRank(rs.getInt("level"), rs
                                                .getString("char_name")));
                        }
                        Collections.sort(_LevelRank_Wizard);

                        // Elf Level Rank
                        _LevelRank_Elf.clear();
                        pstm = con
                                        .prepareStatement("select level,char_name from characters where (class = 37 or class = 138)  and accesslevel = 0 order by exp desc limit 0,10");
                        rs = pstm.executeQuery();
                        while (rs.next()) {
                                _LevelRank_Elf.add(new LevelRank(rs.getInt("level"), rs
                                                .getString("char_name")));
                        }
                        Collections.sort(_LevelRank_Elf);

                        // DarkElf Level Rank
                        _LevelRank_DarkElf.clear();
                        pstm = con
                                        .prepareStatement("select level,char_name from characters where (class = 2786 or class = 2796)  and accesslevel = 0 order by exp desc limit 0,10");
                        rs = pstm.executeQuery();
                        while (rs.next()) {
                                _LevelRank_DarkElf.add(new LevelRank(rs.getInt("level"), rs
                                                .getString("char_name")));
                        }
                        Collections.sort(_LevelRank_DarkElf);

                        // DragonKnight Level Rank
                        _LevelRank_DragonKnight.clear();
                        pstm = con
                                        .prepareStatement("select level,char_name from characters where (class = 6658 or class = 6661)  and accesslevel = 0 order by exp desc limit 0,10");
                        rs = pstm.executeQuery();
                        while (rs.next()) {
                                _LevelRank_DragonKnight.add(new LevelRank(rs.getInt("level"),
                                                rs.getString("char_name")));
                        }
                        Collections.sort(_LevelRank_DragonKnight);

                        // Illusionist Level Rank
                        _LevelRank_Illusionist.clear();
                        pstm = con
                                        .prepareStatement("select level,char_name from characters where (class = 6671 or class = 6650)  and accesslevel = 0 order by exp desc limit 0,10");
                        rs = pstm.executeQuery();
                        while (rs.next()) {
                                _LevelRank_Illusionist.add(new LevelRank(rs.getInt("level"), rs
                                                .getString("char_name")));
                        }
                        Collections.sort(_LevelRank_Illusionist);

                        // ExtLevel Level Rank
                        _LevelRank_ExtLevel.clear();
                        pstm = con
                                        .prepareStatement("select extendlevel,char_name from characters where accesslevel = 0 order by extendlevel desc limit 0,50");
                        rs = pstm.executeQuery();
                        while (rs.next()) {
                                _LevelRank_ExtLevel.add(new LevelRank(rs.getInt("extendlevel"), rs
                                                .getString("char_name")));
                        }
                        Collections.sort(_LevelRank_ExtLevel);

                        // Wepaon enchant Rank
                        _ItemRank_Weapon.clear();
                        pstm = con
                                        .prepareStatement("select characters.char_name ,item.enchantlvl,item.item_name from character_items item left outer join characters on characters.objid = item.char_id where enchantlvl > 5 and (select accesslevel from characters where objid = item.char_id) = 0 and (select name from weapon where item.item_id = weapon.item_id) is not null order by item.enchantlvl desc limit 0,30");
                        rs = pstm.executeQuery();
                        while (rs.next()) {
                                _ItemRank_Weapon.add(new ItemRank(rs.getString("char_name"), rs
                                                .getInt("enchantlvl"), rs.getString("item_name")));
                        }
                        Collections.sort(_ItemRank_Weapon);

                        // Armor enchant Rank
                        _ItemRank_Armor.clear();
                        pstm = con
                                        .prepareStatement("select characters.char_name ,item.enchantlvl,item.item_name from character_items item left outer join characters on characters.objid = item.char_id where enchantlvl > 3 and (select accesslevel from characters where objid = item.char_id) = 0 and (select name from armor where item.item_id = armor.item_id) is not null order by item.enchantlvl desc limit 0,30");
                        rs = pstm.executeQuery();
                        while (rs.next()) {
                                _ItemRank_Armor.add(new ItemRank(rs.getString("char_name"), rs
                                                .getInt("enchantlvl"), rs.getString("item_name")));
                        }
                        Collections.sort(_ItemRank_Armor);
                } catch (SQLException e) {
                        _log.log(Level.SEVERE, e.getLocalizedMessage(), e);
                } finally {
                        SQLUtil.close(rs, pstm, con);
                }
        }

        class ItemRank implements Comparable<ItemRank> {
                ItemRank(String charName, int enchant, String itemName) {
                        _charName = charName;
                        _enchant = enchant;
                        _itemName = itemName;
                }

                int _enchant;
                String _charName;
                String _itemName;

                @Override
                public int compareTo(ItemRank o) {
                        if (this._enchant > o._enchant) {
                                return -1;
                        } else if (this._enchant < o._enchant) {
                                return 1;
                        }
                        return 0;
                }
        }

        class LevelRank implements Comparable<LevelRank> {
                LevelRank(int lv, String name) {
                        _level = lv;
                        _name = name;
                }

                int _level;
                String _name;

                @Override
                public int compareTo(LevelRank o) {
                        if (this._level > o._level) {
                                return -1;
                        } else if (this._level < o._level) {
                                return 1;
                        }
                        return 0;
                }
        }
}